package cn.iocoder.boot.service.impl.supplier;

import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.boot.entity.ComponentPrice;
import cn.iocoder.boot.entity.ComponentStock;
import cn.iocoder.boot.enums.SupplierCodeEnum;
import cn.iocoder.boot.service.CallLimitService;
import cn.iocoder.boot.service.ComponentPriceService;
import cn.iocoder.boot.service.ComponentStockService;
import cn.iocoder.boot.service.HttpRequestLogService;
import cn.iocoder.boot.service.impl.SalePriceConfigServiceImpl;
import cn.iocoder.boot.utils.MessageUtil;
import cn.iocoder.boot.vo.PricingVO;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Digikey 供应商服务实现类
 * 功能：获取Token、查询组件库存与价格信息
 */
@Service
@DS("master")
@Slf4j
public class DigikeyServiceImpl {


    // 接口配置常量（统一常量定义，提升可维护性）
    private static final String TOKEN_URL = "https://api.digikey.com/v1/oauth2/token";
    private static final String PRODUCT_DETAIL_URL = "http://8.155.30.82:5000/api/DigikeyApi/GetProductDetails";
    private static final String KEYWORD_SEARCH_URL = "http://8.155.30.82:5000/api/DigikeyApi/GetQuote";
    private static final String CLIENT_ID = "lnGfrAAGJZMWdzRYe7eJTEn5tgEl0eKc";
    private static final String CLIENT_SECRET = "1aUJX2eqqnh9oaja";
    private static final String GRANT_TYPE = "client_credentials";
    private static final String REDIS_TOKEN_KEY = "supplier:digitoken";
    private static final String LOCALE_LANGUAGE = "zhs";
    private static final String LOCALE_SITE = "CN";
    private static final String CUSTOMER_ID = "10183130";
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Resource
    private ComponentStockService componentStockService;
    @Resource
    private SalePriceConfigServiceImpl salePriceConfigService;
    @Resource
    private ComponentPriceService componentPriceService;
    @Resource
    private CallLimitService callLimitService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Resource(name = "componentExecutor")
    private ThreadPoolExecutor componentExecutor;
    @Resource
    private HttpRequestLogService httpRequestLogService;

    /**
     * 更新Token并存储到Redis
     *
     * @return 最新的Access Token
     */
    public String updateToken() {
        // 最大重试次数
        int maxRetries = 3;
        // 当前重试次数
        int retryCount = 0;

        while (retryCount <= maxRetries) {
            try {
                // 构建表单参数（使用URLEncoder确保特殊字符编码正确）
                String formData = String.format("client_id=%s&client_secret=%s&grant_type=%s",
                        URLEncoder.encode(CLIENT_ID, StandardCharsets.UTF_8),
                        URLEncoder.encode(CLIENT_SECRET, StandardCharsets.UTF_8),
                        URLEncoder.encode(GRANT_TYPE, StandardCharsets.UTF_8));

                // 使用HttpRequest获取完整响应（便于获取状态码）
                HttpResponse response = HttpRequest.post(TOKEN_URL)
                        .header("Content-Type", "application/x-www-form-urlencoded")
                        .timeout(7000)
                        .body(formData)
                        .execute();
                String responseBody = response.body();
                int statusCode = response.getStatus();

                // 保存请求日志（包含状态码）
                httpRequestLogService.saveHttpRequestLog(TOKEN_URL, "digiKey_token", formData, responseBody, statusCode);

                // 日志打印（包含时间和状态码）
                String currentTime = DATE_FORMAT.format(new Date());
                log.info("{} Token获取结果: 状态码={}, 响应体={}", currentTime, statusCode, responseBody);

                // 处理非200状态码
                if (statusCode != 200) {
                    log.error("Token请求失败，状态码: {}", statusCode);

                    // 服务器错误（5xx）且未达最大重试次数时重试
                    if ((statusCode >= 500 && statusCode < 600) && retryCount < maxRetries) {
                        retryCount++;
                        log.warn("遇到{}错误，将进行第{}次重试（共{}次）", statusCode, retryCount, maxRetries);
                        Thread.sleep(1000); // 延迟1秒重试
                        continue;
                    }

                    // 非重试场景直接抛出异常
                    throw new RuntimeException("Token获取失败，状态码: " + statusCode);
                }

                // 解析响应JSON
                JSONObject jsonObject = JSONUtil.parseObj(responseBody);

                // 提取Token和过期时间
                String token = jsonObject.getStr("access_token");
                Long expireSeconds = jsonObject.getLong("expires_in");

                // 校验Token有效性
                if (StringUtils.isNotBlank(token) && expireSeconds != null && expireSeconds > 0) {
                    stringRedisTemplate.opsForValue().set(REDIS_TOKEN_KEY, token, expireSeconds - 100, TimeUnit.SECONDS);
                    return token;
                }

                // Token无效时的重试处理
                log.error("Token响应中未包含有效的access_token或expires_in");
                if (retryCount < maxRetries) {
                    retryCount++;
                    log.warn("Token无效，将进行第{}次重试（共{}次）", retryCount, maxRetries);
                    Thread.sleep(200);
                    continue;
                }

                // 无效Token且无法重试时抛出异常
                throw new RuntimeException("Token响应中未包含有效的access_token或expires_in");

            } catch (HttpException e) {
                log.error("Token请求HTTP异常（第{}次尝试）", retryCount + 1, e);

                // 处理超时类异常的重试
                if (e.getMessage() != null && (e.getMessage().contains("Connect timed out")
                        || e.getMessage().contains("Connection timed out")
                        || e.getMessage().contains("Read timed out")) && retryCount < maxRetries) {
                    retryCount++;
                    String token = stringRedisTemplate.opsForValue().get(REDIS_TOKEN_KEY);
                    if (StringUtils.isNotBlank(token)) {
                        return token;
                    }
                    log.warn("遇到连接超时，将进行第{}次重试（共{}次）", retryCount, maxRetries);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("重试等待被中断", ie);
                    }
                    continue;
                }

                // 非重试场景的HTTP异常
                throw new RuntimeException("Token获取失败", e);

            } catch (InterruptedException e) {
                log.error("重试等待被中断", e);
                Thread.currentThread().interrupt();
                throw new RuntimeException("Token获取过程被中断", e);

            } catch (Exception e) {
                log.error("Token获取处理异常（第{}次尝试）", retryCount + 1, e);

                // 其他异常的重试处理
                if (retryCount < maxRetries) {
                    retryCount++;
                    log.warn("发生未知异常，将进行第{}次重试（共{}次）", retryCount, maxRetries);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("重试等待被中断", ie);
                    }
                    continue;
                }

                // 所有重试失败
                throw new RuntimeException("Token获取失败", e);
            }
        }

        // 达到最大重试次数
        throw new RuntimeException("已达到最大重试次数（" + maxRetries + "次），Token获取失败");
    }

    /**
     * 获取Token（优先从Redis读取，失效则更新）
     *
     * @return 有效的Access Token
     */
    public String getToken() {
        String token = stringRedisTemplate.opsForValue().get(REDIS_TOKEN_KEY);
        return StringUtils.isNotBlank(token) ? token : updateToken();
    }

    /**
     * 批量查询组件价格与库存信息
     *
     * @param listByIds            组件库存列表
     * @param currency             货币类型（如CNY）
     * @param componentSupplierMap 供应商系数映射
     * @throws Exception 异常信息
     */
    public List<ComponentPrice> query(List<ComponentStock> listByIds, String currency, Map<String, BigDecimal> componentSupplierMap) {
        // 1. 过滤得捷电子供应商的组件，提取型号和ID映射
        List<String> models = listByIds.stream()
                .filter(stock -> Objects.equals(stock.getSupplierCode(), SupplierCodeEnum.DIGIKEY.getCode()))
                .map(ComponentStock::getPartnumber)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(models)) {
            log.info("无得捷电子供应商的组件需要查询");
            return new ArrayList<>();
        }

        // 2. 获取Token，批量查询组件信息
        String token = getToken();
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        List<ComponentPrice> componentPriceList = new CopyOnWriteArrayList<>(); // 线程安全的列表
        long startTime = System.currentTimeMillis();
        for (String partNumber : models) {
            // 创建异步任务
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                // 接口调用限流
                callLimitService.supplierLimitCall(SupplierCodeEnum.DIGIKEY.getCode());
                // 调用带重试机制的查询方法
                queryWithRetry(partNumber, token, currency, componentSupplierMap, componentPriceList);
            }, componentExecutor);

            futures.add(future);
        }


        // 等待所有异步任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        long endTime = System.currentTimeMillis();

        long duration = endTime - startTime;
        log.info("耗时--query-: {}", duration);
        // 按原始models顺序重新排列结果
        List<ComponentPrice> orderedResult = new ArrayList<>(models.size());
        for (String model : models) {
            // 找到对应uniqueId的ComponentPrice
            for (ComponentPrice price : componentPriceList) {
                if (model.equals(price.getModel())) {
                    orderedResult.add(price);
                    break;
                }
            }
        }

        // 批量保存价格信息 (这里可以选择保存原始列表或排序后的列表)
        if (CollectionUtils.isNotEmpty(componentPriceList)) {
            componentPriceList.forEach(x -> componentPriceService.createComponentPriceOfUniqueKey(x));
            log.info("批量保存得捷电子组件价格成功，共{}条记录", componentPriceList.size());
        } else {
            log.info("无得捷电子组件价格需要保存");
        }

        // 返回排序后的结果
        return orderedResult;
    }

    /**
     * 带重试机制的查询方法
     */
    private void queryWithRetry(String partNumber, String token, String currency,
                                Map<String, BigDecimal> componentSupplierMap,
                                List<ComponentPrice> componentPriceList) {
        int maxRetries = 3;
        int retryCount = 0;
        boolean success = false;

        while (retryCount < maxRetries && !success) {
            try {
                // 构建编码后的请求URL
//                String encodedPartNumber = URLEncoder.encode(partNumber, StandardCharsets.UTF_8);
//                String requestUrl = String.format(PRODUCT_DETAIL_URL, encodedPartNumber);
                String jsonBody = "{"
                        + "\"KeyWord\": \"" + partNumber.replace("/", "%2F").replace("#", "%23") + "\","
                        + "\"Currency\": \"" + currency + "\","
                        + "\"token\": \"" + token + "\""
                        + "}";
                // 发送GET请求
                HttpResponse response = HttpRequest.post(PRODUCT_DETAIL_URL)
                        .header("X-DIGIKEY-Client-Id", CLIENT_ID)
                        .header("X-DIGIKEY-Locale-Language", LOCALE_LANGUAGE)
                        .header("X-DIGIKEY-Locale-Currency", currency)
                        .header("X-DIGIKEY-Locale-Site", LOCALE_SITE)
                        .header("X-DIGIKEY-Customer-Id", CUSTOMER_ID)
                        .header("Authorization", "Bearer " + token)
                        .body(jsonBody)
                        .timeout(7000)
                        .execute();

                httpRequestLogService.saveHttpRequestLog(PRODUCT_DETAIL_URL, "digiKey_queryWithRetry", partNumber, response.body(), response.getStatus());

                // 处理响应
                if (response.getStatus() == 200) {
                    success = true; // 成功获取响应，标记为成功
                    String responseBody = response.body();
                    log.info("得捷电子组件[{}]价格查询响应: {}", partNumber, responseBody);

                    JSONObject jsonResponse = JSONUtil.parseObj(responseBody);
                    JSONObject product = jsonResponse.getJSONObject("Product");
                    if (product == null) {
                        log.warn("Digikey组件[{}]无产品信息", partNumber);
                        return;
                    }

                    JSONArray productVariations = product.getJSONArray("ProductVariations");
                    if (CollectionUtils.isEmpty(productVariations)) {
                        log.warn("得捷电子组件[{}]无产品变体信息", partNumber);
                        return;
                    }

                    // 遍历产品变体，构建价格和库存信息
                    for (Object variationObj : productVariations) {
                        JSONObject variation = JSONUtil.parseObj(variationObj);
                        if (Objects.equals(variation.getStr("DigiKeyProductNumber"), partNumber)) {
                            buildComponentPrice(variation, product, partNumber, currency, componentSupplierMap, componentPriceList);
                        }
                    }
                } else {
                    log.error("得捷电子组件[{}]查询失败，状态码: {}, 响应: {}",
                            partNumber, response.getStatus(), response.body());

                    // 判断是否需要重试（502状态码）
                    if (response.getStatus() == 502 && retryCount < maxRetries - 1) {
                        retryCount++;
                        log.info("得捷电子组件[{}]将进行第{}次重试...", partNumber, retryCount);
                        continue; // 继续重试循环
                    }

                    // 不需要重试或达到最大重试次数，发送消息
                    MessageUtil.sentMessage("26827", "得捷电子查询型号价格http失败" + response.body(), "得捷电子查询型号价格http失败");
                    success = true; // 标记为成功处理（避免无限循环）
                }
            } catch (Exception e) {
                log.error("得捷电子组件[{}]查询异常（第{}次尝试）", partNumber, retryCount + 1, e);

                // 判断是否需要重试（连接超时）
                if (e.getMessage() != null && (e.getMessage().contains("Connect timed out") || e.getMessage().contains("Connection timed out") || e.getMessage().contains("Read timed out")) && retryCount < maxRetries) {
                    retryCount++;
                    log.info("得捷电子组件[{}]将进行第{}次重试...", partNumber, retryCount);
                    continue; // 继续重试循环
                }

                // 不需要重试或达到最大重试次数，发送消息
                MessageUtil.sentMessage("26827", "得捷电子查询型号价格异常" + e.getMessage(), "得捷电子查询型号价格异常" + retryCount);
                success = true; // 标记为成功处理（避免无限循环）
            }
        }

        if (retryCount >= maxRetries) {
            log.error("得捷电子组件[{}]达到最大重试次数({}次)，查询失败", partNumber, maxRetries);
        }
    }


    /**
     * 单个组件查询（按型号关键词搜索）
     *
     * @param model    组件型号
     * @param currency 货币类型
     * @throws Exception 异常信息
     */
    public List<ComponentPrice> queryOne(String model, String currency, Map<String, BigDecimal> componentSupplierMap) {
        if (StringUtils.isBlank(model)) {
            log.error("组件型号不能为空");
            throw new IllegalArgumentException("组件型号不能为空");
        }

        String token = getToken();
        callLimitService.supplierLimitCall(SupplierCodeEnum.DIGIKEY.getCode());

        // 最大重试次数
        int maxRetries = 5;
        // 当前重试次数
        int retryCount = 0;

        while (retryCount <= maxRetries) {
            try {
                // 构建JSON请求体（使用Hutool JSONUtil避免手动拼接JSON）
                JSONObject requestBody = JSONUtil.createObj();
                requestBody.put("KeyWord", model);
                requestBody.put("token", token);
                requestBody.put("Currency", currency);
                String jsonBody = requestBody.toString();

                long startTime = System.currentTimeMillis();
                // Hutool HttpRequest构建POST请求（设置Content-Type为JSON）
                HttpResponse response = HttpRequest.post(KEYWORD_SEARCH_URL)
                        .timeout(8000)
                        .body(jsonBody)
                        .execute();
                long endTime = System.currentTimeMillis();

                long duration = endTime - startTime;
                log.info("耗时queryOne---: {}", duration);
                httpRequestLogService.saveHttpRequestLog(KEYWORD_SEARCH_URL, "digiKey_queryOne", model, response.body(), response.getStatus());

                // 处理响应
                if (response.getStatus() == 200) {
                    String responseBody = response.body();
                    log.info("得捷电子单个组件[{}]搜索响应: {}", model, responseBody);

                    JSONObject jsonResponse = JSONUtil.parseObj(responseBody);
                    JSONArray products = jsonResponse.getJSONArray("Products");
                    if (CollectionUtils.isEmpty(products)) {
                        log.warn("得捷电子组件[{}]未搜索到结果", model);
                        return null;
                    }

                    // 遍历产品，精准匹配型号后保存库存
                    List<ComponentStock> stockList = new ArrayList<>();

                    // 将 JSONArray 转为 List<JSONObject>，方便集合操作
                    List<JSONObject> productsList = new ArrayList<>();
                    for (int i = 0; i < products.size(); i++) {
                        productsList.add(products.getJSONObject(i));
                    }

                    // 自定义排序：ManufacturerProductNumber 等于 model 的元素排前面
                    Collections.sort(productsList, new Comparator<JSONObject>() {
                        @Override
                        public int compare(JSONObject product1, JSONObject product2) {
                            // 获取两个产品的 ManufacturerProductNumber
                            String mpn1 = product1.getStr("ManufacturerProductNumber", "");
                            String mpn2 = product2.getStr("ManufacturerProductNumber", "");

                            // 判断是否等于 model（MAX3072EASA+T）
                            boolean isMpn1Target = mpn1.equals(model);
                            boolean isMpn2Target = mpn2.equals(model);

                            // 排序规则：目标型号排前面，非目标型号排后面；若同为目标/非目标，保持原相对顺序（返回 0）
                            if (isMpn1Target && !isMpn2Target) {
                                return -1; // product1 排前面
                            } else if (!isMpn1Target && isMpn2Target) {
                                return 1; // product2 排前面
                            } else {
                                return 0; // 保持原相对顺序
                            }
                        }
                    });

                    for (Object productObj : productsList) {
                        JSONObject product = JSONUtil.parseObj(productObj);
                        JSONArray variations = product.getJSONArray("ProductVariations");
                        if (CollectionUtils.isEmpty(variations)) {
                            continue;
                        }

                        for (Object variationObj : variations) {
                            JSONObject variation = JSONUtil.parseObj(variationObj);
                            // 构建组件库存信息并保存
                            ComponentStock stock = buildComponentStock(product, variation, model);
                            JSONObject classifications = product.getJSONObject("Classifications");
                            if (Objects.nonNull(classifications)) {
                                stock.setExportControlClassificationNumber(classifications.getStr("ExportControlClassNumber"));
                            }
                            String standardPricing = variation.getStr("StandardPricing");
                            if (StringUtils.isNotEmpty(standardPricing)) {
                                List<PricingVO> pricingVOList = JSONUtil.toList(standardPricing, PricingVO.class);
                                for (PricingVO standardPrice : pricingVOList) {
                                    stock.setMinNum(standardPrice.getBreakQuantity());
                                    break;
                                }
                            }
                            stockList.add(stock);
                            componentStockService.saveComponentStockOfUniqueKey(stock);
                            log.info("得捷电子组件[{}]库存保存成功，ID: {}", model, stock.getId());
                        }
                    }
                    Map<String, ComponentStock> componentStockMap = stockList.stream().collect(Collectors.toMap(
                            ComponentStock::getUniqueId,
                            Function.identity(),
                            (existing, replacement) -> replacement
                    ));
                    List<ComponentPrice> componentPriceList = query(stockList, currency, componentSupplierMap);
                    componentPriceList.forEach(x -> x.setStockInfo(componentStockMap.get(x.getUniqueId())));
                    return componentPriceList;
                } else {
                    log.error("得捷电子单个组件[{}]搜索失败，状态码: {}, 响应: {}",
                            model, response.getStatus(), response.body());

                    // 如果是502错误且未达到最大重试次数，则进行重试
                    if (response.getStatus() == 502 && retryCount < maxRetries) {
                        retryCount++;
                        log.warn("遇到502错误，将进行第{}次重试（共{}次）", retryCount, maxRetries);
                        // 可以添加短暂延迟再重试，避免频繁请求
                        Thread.sleep(200);
                        continue;
                    }

                    MessageUtil.sentMessage("26827", "得捷电子查询型号失败" + response.body(), "得捷电子查询型号失败");
                    return new ArrayList<>();
                }
            } catch (HttpException e) {
                log.error("得捷电子单个组件[{}]搜索HTTP异常", model, e);

                // 检查异常信息中是否包含Connection timed out，并且未达到最大重试次数
                if (e.getMessage() != null && (e.getMessage().contains("Connect timed out") || e.getMessage().contains("Connection timed out") || e.getMessage().contains("Read timed out"))
                        && retryCount < maxRetries) {
                    retryCount++;
                    log.warn("遇到连接超时，将进行第{}次重试（共{}次）", retryCount, maxRetries);
                    // 可以添加短暂延迟再重试
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                    continue;
                }

                MessageUtil.sentMessage("26827", "得捷电子查询型号异常" + e.getMessage(), "得捷电子查询型号异常" + retryCount);
                break; // 不满足重试条件，退出循环
            } catch (InterruptedException e) {
                log.error("重试等待被中断", e);
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                log.error("得捷电子单个组件[{}]处理异常", model, e);
                // 检查异常信息中是否包含Connection timed out，并且未达到最大重试次数
                if (e.getMessage() != null && (e.getMessage().contains("Connect timed out") || e.getMessage().contains("Connection timed out") || e.getMessage().contains("Read timed out"))
                        && retryCount < maxRetries) {
                    retryCount++;
                    log.warn("遇到连接超时，将进行第{}次重试（共{}次）", retryCount, maxRetries);
                    // 可以添加短暂延迟再重试
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                    continue;
                }

                MessageUtil.sentMessage("26827", "得捷电子查询型号异常" + e.getMessage(), "得捷电子查询型号异常" + retryCount);
                break; // 其他异常不重试
            }
        }

        // 所有重试都失败的情况下返回空列表
        return new ArrayList<>();
    }


    /**
     * 构建组件价格对象（抽取工具方法，减少重复代码）
     */
    private void buildComponentPrice(JSONObject variation, JSONObject product, String partNumber,
                                     String currency,
                                     Map<String, BigDecimal> componentSupplierMap,
                                     List<ComponentPrice> componentPriceList) {

        String model = variation.getStr("DigiKeyProductNumber");
        Long availableQuantity = variation.getLong("QuantityAvailableforPackageType");
        String packageName = variation.getJSONObject("PackageType").getStr("Name");
        BigDecimal supplierCoeff = componentSupplierMap.getOrDefault(
                SupplierCodeEnum.DIGIKEY.getCode(), BigDecimal.valueOf(2));

        // 2. 解析自定义价格（MyPricing）
        JSONArray myPricingArray = variation.getJSONArray("MyPricing");
        JSONArray formattedMyPricing = formatPricingArray(myPricingArray, currency);

        // 3. 解析标准价格（StandardPricing）
        JSONArray standardPricingArray = variation.getJSONArray("StandardPricing");
        JSONArray formattedStandardPricing = formatPricingArray(standardPricingArray, currency);

        // 4. 生成销售价格JSON
        String saleJson = salePriceConfigService.getSaleJson(
                formattedStandardPricing.toString(), model, currency);

        // 5. 构建价格对象并添加到列表
        ComponentPrice componentPrice = new ComponentPrice(
                SupplierCodeEnum.DIGIKEY.getCode() + "_" + partNumber,
                formattedMyPricing.toString(),
                availableQuantity,
                null,
                packageName,
                currency,
                model,
                formattedStandardPricing.toString(),
                saleJson,
                supplierCoeff
        );
        componentPriceList.add(componentPrice);
    }

    /**
     * 构建组件库存对象（抽取工具方法，减少重复代码）
     */
    private ComponentStock buildComponentStock(JSONObject product, JSONObject variation, String model) {
        ComponentStock stock = new ComponentStock();
        stock.setModel(product.getStr("ManufacturerProductNumber"));
        stock.setPicUrl(product.getStr("PhotoUrl"));
        stock.setPartnumber(variation.getStr("DigiKeyProductNumber"));
        stock.setKeyword(model);
        stock.setType(product.getJSONObject("Category").getStr("Name"));
        stock.setBrand(product.getJSONObject("Manufacturer").getStr("Name"));
        stock.setSpecifications(product.getJSONObject("Description").getStr("DetailedDescription"));
        stock.setStockType(1);
        stock.setSupplierCode(SupplierCodeEnum.DIGIKEY.getCode());
        stock.setUniqueId(SupplierCodeEnum.DIGIKEY.getCode() + "_" + variation.getStr("DigiKeyProductNumber"));
        return stock;
    }

    /**
     * 格式化价格数组（统一保留4位小数，封装为标准结构）
     */
    private JSONArray formatPricingArray(JSONArray pricingArray, String currency) {
        JSONArray resultArray = new JSONArray();
        if (CollectionUtils.isEmpty(pricingArray)) {
            return resultArray;
        }

        for (Object pricingObj : pricingArray) {
            JSONObject pricing = JSONUtil.parseObj(pricingObj);
            String unitPriceStr = pricing.getStr("UnitPrice");
            String breakQuantity = pricing.getStr("BreakQuantity");

            // 价格格式化：转Double后保留4位小数
            BigDecimal formattedPrice = new BigDecimal(unitPriceStr);
            // 构建标准价格结构
            JSONObject priceInfo = JSONUtil.createObj();
            priceInfo.put("Price", formattedPrice);
            priceInfo.put("Currency", currency);
            priceInfo.put("Quantity", breakQuantity);
            resultArray.add(priceInfo);
        }
        return resultArray;
    }
}